package com.heima.comment.service.impl;

import com.heima.apis.article.IArticleClient;
import com.heima.apis.user.IUserClient;
import com.heima.apis.wemedia.IWemediaClient;
import com.heima.comment.service.CommentService;
import com.heima.model.comment.dtos.ApCommentDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.pojos.ApCommentRepay;
import com.heima.model.comment.vos.ApCommentRepayVo;
import com.heima.model.comment.vos.ApCommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.wemedia.pojos.WmSensitive;
import com.heima.model.wemedia.utils.AppThreadLocalUtils;
import com.heima.utils.common.SensitiveWordUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private IWemediaClient wemediaClient;
    @Autowired
    private IUserClient userClient;
    @Autowired
    private KafkaTemplate kafkaTemplate;
    @Autowired
    private IArticleClient articleClient;


    /**
     * 查询文章评论列表
     * @param dto
     * @return
     */
    @Override
    public ResponseResult loadComment(ApCommentDto dto) {

        if (dto.getArticleId()==null){
           return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        List<ApComment> entryId = mongoTemplate
                .find(Query.query(Criteria.where("entryId").is(dto.getArticleId())), ApComment.class)
                .stream().limit(10)
                .sorted(Comparator.comparing(ApComment::getCreatedTime).reversed())
                .skip((dto.getIndex()-1) * 10)
                .collect(Collectors.toList());

        List apCommentVoList = new ArrayList();
        for (ApComment apComment : entryId) {
            ApCommentVo apCommentVo = new ApCommentVo();
            BeanUtils.copyProperties(apComment,apCommentVo);

            Criteria criteria = new Criteria();
            criteria.andOperator(
                    Criteria.where("commentId").is(apComment.getId()),
                    Criteria.where("authorId").is(AppThreadLocalUtils.getUser().getId())
            );
            if (mongoTemplate.exists(Query.query(criteria),ApCommentLike.class)){
                apCommentVo.setOperation(0);
            }
            apCommentVoList.add(apCommentVo);
        }



        ResponseResult responseResult = new ResponseResult();
        responseResult.setData(apCommentVoList);


        return responseResult;
    }

    /**
     * 添加评论数据
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(ApCommentDto dto) {
        //参数校验
        if (dto.getArticleId() == null || StringUtils.isEmpty(dto.getContent())){
            ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //判断用户是否登录,登录才可评论
        Integer userId = AppThreadLocalUtils.getUser().getId();
        if (userId == null){
           return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //状态未不能评论时,不可评论
        String isComment = articleClient.getIsComment(dto.getArticleId());
        if (isComment.equals("false")){
            return ResponseResult.errorResult(AppHttpCodeEnum.CANNOT_COMMENT);
        }


        //获取用户名字
        String userName = userClient.getUserName(userId);


        //评论内容校验
        boolean flag = handleSensitiveScan(dto.getContent());

        //审核有问题
        if (!flag){
            return ResponseResult.errorResult((AppHttpCodeEnum.MATERIAL_NEWS_FAIL));
        }

        //审核没问题
        ApComment apComment = new ApComment();
        apComment.setAuthorId(userId);
        apComment.setAuthorName(userName);
        apComment.setEntryId(dto.getArticleId());
        apComment.setContent(dto.getContent());
        apComment.setCreatedTime(new Date());
        apComment.setReply(0);
        apComment.setLikes(0);

        //保存数据
        mongoTemplate.save(apComment);

        //kafka同步数据库
        kafkaTemplate.send("comment", dto.getArticleId().toString());


        return ResponseResult.okResult("评论成功");
    }

    /**
     * 点赞与取消点赞评论
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult likeComment(ApCommentDto dto) {
        //参数校验
        if (dto.getCommentId() == null || dto.getOperation() == null){
            ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }


        //获取评论信息
        ApComment comment = mongoTemplate.findOne(Query.query(Criteria.where("_id").is(dto.getCommentId())), ApComment.class);

        Integer likes = comment.getLikes();

        if (dto.getOperation() == 0){
            //点赞
            likes++;
            //保存点赞关系
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(AppThreadLocalUtils.getUser().getId());
            apCommentLike.setCommentId(dto.getCommentId());
            mongoTemplate.save(apCommentLike);
        }else {
            //取消点赞
            likes = likes > 0 ? likes-1 : 0;
            mongoTemplate.remove(Query.query(Criteria.where("commentId").is(comment.getId())),ApCommentLike.class);
        }

        Update update = new Update();
        mongoTemplate.updateFirst(Query.query(Criteria.where("_id").is(dto.getCommentId())),update.set("likes",likes),ApComment.class);



        return ResponseResult.okResult("点赞成功");
    }

    /**
     * 点赞或取消点赞评论回复
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult likeRepayComment(ApCommentDto dto) {
        //参数校验
        if (dto.getCommentRepayId() == null || dto.getOperation() == null){
            ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //获取评论信息
        ApCommentRepay commentRepay = mongoTemplate.findOne(Query.query(Criteria.where("_id").is(dto.getCommentRepayId())), ApCommentRepay.class);
        Integer likes = commentRepay.getLikes();

        if (dto.getOperation() == 0){
            //点赞
            likes++;
            //保存点赞关系
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setAuthorId(AppThreadLocalUtils.getUser().getId());
            apCommentLike.setCommentId(dto.getCommentRepayId());
            mongoTemplate.save(apCommentLike);
        }else {
            //取消点赞
            likes = likes > 0 ? likes-1 : 0;
            mongoTemplate.remove(Query.query(Criteria.where("commentId").is(dto.getCommentRepayId())),ApCommentLike.class);
        }

        Update update = new Update();
        mongoTemplate.updateFirst(Query.query(Criteria.where("_id").is(dto.getCommentId())),update.set("likes",likes),ApComment.class);


        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 评论回复添加
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveRepayComment(ApCommentDto dto) {
        //参数校验
        if (dto.getCommentId() == null || StringUtils.isEmpty(dto.getContent())){
            ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (dto.getContent().length()>140){
            ResponseResult.errorResult(AppHttpCodeEnum.TOO_LONG);
        }

        //判断用户是否登录,登录才可评论
        Integer userId = AppThreadLocalUtils.getUser().getId();
        if (userId == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        //获取用户名字
        String userName = userClient.getUserName(userId);


        //评论内容校验
        boolean flag = handleSensitiveScan(dto.getContent());

        //审核有问题
        if (!flag){
            return ResponseResult.errorResult((AppHttpCodeEnum.MATERIAL_NEWS_FAIL));
        }
        //审核没问题,保存数到数据库
        ApCommentRepay apCommentRepay = new ApCommentRepay();
        apCommentRepay.setAuthorId(userId);
        apCommentRepay.setAuthorName(userName);
        apCommentRepay.setCommentId(dto.getCommentId());
        apCommentRepay.setContent(dto.getContent());
        apCommentRepay.setLikes(0);
        apCommentRepay.setCreatedTime(new Date());
        apCommentRepay.setUpdateTime(new Date());
        mongoTemplate.save(apCommentRepay);


        ApComment comment = mongoTemplate.findOne(Query.query(Criteria.where("_id").is(dto.getCommentId())), ApComment.class);
        Integer reply = comment.getReply();
        int repay = reply + 1;

        Update update = new Update();
        mongoTemplate.updateFirst(Query.query(Criteria.where("_id").is(dto.getCommentId())),update.set("reply",repay),ApComment.class);


        return ResponseResult.okResult("评论回复成功");
    }

    /**
     * 评论回复加载
     *
     * @param dto
     * @return
     */
    @Override
    public ResponseResult loadRepayComment(ApCommentDto dto) {
        if (dto.getCommentId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }


        Integer userId = AppThreadLocalUtils.getUser().getId();
        if (userId == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }

        Criteria criteria1 = new Criteria();
        criteria1.andOperator(
                Criteria.where("commentId").is(dto.getCommentId()),
                Criteria.where("createdTime").lt(dto.getMinDate())
        );

        List<ApCommentRepay> commentRepays = mongoTemplate
                .find(Query.query(criteria1), ApCommentRepay.class)
                .stream().limit(10)
                .sorted(Comparator.comparing(ApCommentRepay::getCreatedTime).reversed())
                .collect(Collectors.toList());

        List<ApCommentRepayVo> apCommentRepayVos = new ArrayList<>();
        for (ApCommentRepay commentRepay : commentRepays) {
            ApCommentRepayVo apCommentRepayVo = new ApCommentRepayVo();
            BeanUtils.copyProperties(commentRepay,apCommentRepayVo);

            Criteria criteria2 = new Criteria();
            criteria2.andOperator(
                    Criteria.where("commentId").is(commentRepay.getId()),
                    Criteria.where("authorId").is(AppThreadLocalUtils.getUser().getId())
            );

            if (mongoTemplate.exists(Query.query(criteria2),ApCommentLike.class)){
                apCommentRepayVo.setOperation(0);
            }
            apCommentRepayVos.add(apCommentRepayVo);
        }


        return ResponseResult.okResult(apCommentRepayVos);
    }


    /**
     * 自定义敏感词过滤，基于DFA算法实现
     * @param content
     */
    private boolean handleSensitiveScan(String content) {
        //标记位：假设审核没问题
        boolean flag = true;

        //查询系统敏感词
//        List<WmSensitive> allSensitive = wmSensitiveMapper.selectList(Wrappers.<WmSensitive>lambdaQuery().select());
        List<WmSensitive> allSensitive = wemediaClient.selectList();
        List<String> list = allSensitive.stream().map(wmSensitive -> wmSensitive.getSensitives()).collect(Collectors.toList());

        //1. 初始化敏感词库
        SensitiveWordUtil.initMap(list);

        //2. 进行敏感词匹配
        Map<String, Integer> resMap = SensitiveWordUtil.matchWords(content);

        //结果处理
        if (!resMap.isEmpty()){
            flag = false;
        }

        return flag;
    }
}
